{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "from aco import ACO\n",
    "import numpy as np\n",
    "import logging\n",
    "from gen_inst import BPPInstance, load_dataset, dataset_conf\n",
    "\n",
    "N_ANTS = 30\n",
    "N_ITERATIONS = [1, 10, 30, 50, 80, 100]\n",
    "\n",
    "\n",
    "def heuristics_reevo(demand: np.ndarray, capacity: int) -> np.ndarray:\n",
    "    n = demand.shape[0]\n",
    "    demand_normalized = demand / demand.max()\n",
    "    \n",
    "    same_bin_penalty = np.abs((capacity - demand[:, None] - demand) / capacity)\n",
    "    overlap_penalty = (demand[:, None] + demand) / capacity\n",
    "    \n",
    "    heuristics = demand_normalized[:, None] + demand_normalized - same_bin_penalty - overlap_penalty\n",
    "    \n",
    "    threshold = np.percentile(heuristics, 90)\n",
    "    heuristics[heuristics < threshold] = 0\n",
    "    \n",
    "    return heuristics\n",
    "\n",
    "\n",
    "def heuristics_human(demand: np.ndarray, capacity: int) -> np.ndarray:\n",
    "    return np.tile(demand/demand.max(), (demand.shape[0], 1))\n",
    "\n",
    "def solve(inst: BPPInstance, heuristics):\n",
    "    heu = heuristics(inst.demands.copy(), inst.capacity) # normalized in ACO\n",
    "    assert tuple(heu.shape) == (inst.n, inst.n)\n",
    "    assert 0 < heu.max() < np.inf\n",
    "    aco = ACO(inst.demands, heu.astype(float), capacity = inst.capacity, n_ants=N_ANTS, greedy=False)\n",
    "\n",
    "    results = []\n",
    "    for i in range(len(N_ITERATIONS)):\n",
    "        if i == 0:\n",
    "            obj, _ = aco.run(N_ITERATIONS[i])\n",
    "        else:\n",
    "            obj, _ = aco.run(N_ITERATIONS[i] - N_ITERATIONS[i-1])\n",
    "        results.append(obj)\n",
    "    return results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[*] Average for 120, 1 iterations: 51.796875\n",
      "[*] Average for 120, 10 iterations: 51.171875\n",
      "[*] Average for 120, 30 iterations: 50.78125\n",
      "[*] Average for 120, 50 iterations: 50.484375\n",
      "[*] Average for 120, 80 iterations: 50.203125\n",
      "[*] Average for 120, 100 iterations: 50.125\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for problem_size in [120]:\n",
    "    dataset_path = f\"dataset/val{problem_size}_dataset.npz\"\n",
    "    dataset = load_dataset(dataset_path)\n",
    "    n_instances = dataset[0].n\n",
    "    logging.info(f\"[*] Evaluating {dataset_path}\")\n",
    "\n",
    "    objs = []\n",
    "    for i, instance in enumerate(dataset):\n",
    "        obj = solve(instance, heuristics_human) # expert-defined heuristics\n",
    "        objs.append(obj)\n",
    "    \n",
    "    # Average objective value for all instances\n",
    "    mean_obj = np.mean(objs, axis=0)\n",
    "    for i, obj in enumerate(mean_obj):\n",
    "        print(f\"[*] Average for {problem_size}, {N_ITERATIONS[i]} iterations: {obj}\")\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[*] Average for 120, 1 iterations: 49.890625\n",
      "[*] Average for 120, 10 iterations: 49.640625\n",
      "[*] Average for 120, 30 iterations: 49.484375\n",
      "[*] Average for 120, 50 iterations: 49.421875\n",
      "[*] Average for 120, 80 iterations: 49.375\n",
      "[*] Average for 120, 100 iterations: 49.375\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for problem_size in [120]:\n",
    "    dataset_path = f\"dataset/val{problem_size}_dataset.npz\"\n",
    "    dataset = load_dataset(dataset_path)\n",
    "    n_instances = dataset[0].n\n",
    "    logging.info(f\"[*] Evaluating {dataset_path}\")\n",
    "\n",
    "    objs = []\n",
    "    for i, instance in enumerate(dataset):\n",
    "        obj = solve(instance, heuristics_reevo) # ReEvo-generated heuristics\n",
    "        objs.append(obj)\n",
    "    \n",
    "    # Average objective value for all instances\n",
    "    mean_obj = np.mean(objs, axis=0)\n",
    "    for i, obj in enumerate(mean_obj):\n",
    "        print(f\"[*] Average for {problem_size}, {N_ITERATIONS[i]} iterations: {obj}\")\n",
    "    print()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
